using System;
using System.Security.Cryptography;
using System.Web;
using System.Web.Security;

namespace BoxBinary.AspectCache.Core.Helpers
{
    /// <summary>
    /// A non-instanciable object with various static methods which relate
    /// to security on the web
    /// </summary>
    public sealed class WebSecurity
    {
        private WebSecurity()
        {
        }

        #region Methods

        /// <summary>
        /// Validates a plain string against a salted hash
        /// </summary>
        /// <param name="StringToValidate">Plain text string to validate</param>
        /// <param name="saltedHash">Origonal salted hash to compare string against</param>
        /// <returns>bool representing whether the string matches the salted hash</returns>
        public static bool ValidateSaltedHash(string StringToValidate, string saltedHash)
        {
            //extract hash and salt string
            string saltString = saltedHash.Substring(saltedHash.Length - 24);
            string hash1 = saltedHash.Substring(0, saltedHash.Length - 24);

            //append the salt string to the password
            string saltedPassword = StringToValidate + saltString;

            //hash the salted password
            string hash2 = FormsAuthentication.HashPasswordForStoringInConfigFile(saltedPassword, "SHA1");

            //compare the hashes
            return (hash1.CompareTo(hash2) == 0);
        }

        /// <summary>
        /// Generates a salted hash from a supplied string
        /// </summary>
        /// <param name="StringToHash">String to salt/hash</param>
        /// <returns>Salted hash</returns>
        public static string CreateSaltedHash(string StringToHash)
        {
            //Generate a random salt string
            var csp = new RNGCryptoServiceProvider();
            var saltBytes = new byte[16];
            csp.GetNonZeroBytes(saltBytes);
            string saltString = Convert.ToBase64String(saltBytes);

            //Append the salt string to the password
            string saltedPassword = StringToHash + saltString;

            //Hash the salted password
            string hash = FormsAuthentication.HashPasswordForStoringInConfigFile(saltedPassword, "SHA1");

            //Append salt to hash
            string saltedHash = hash + saltString;
            return saltedHash;
        }

        /// <summary>
        /// Encrypts a string ready for sending through a querystring
        /// </summary>
        /// <param name="strQuerystring">Querystring to be encrypted</param>
        /// <param name="strEncryptionKey">Key to encrypt the querystring with</param>
        /// <returns>An encrypted ver of the querystring</returns>
        public static string EncryptQuerystring(string strQuerystring, string strEncryptionKey)
        {
            return HttpUtility.UrlEncode(Encryption64.Encrypt(strQuerystring, strEncryptionKey));
        }

        /// <summary>
        /// Decrypts a previously encoded querystring
        /// </summary>
        /// <param name="strEncryptedQuerystring">Encrypted querystring</param>
        /// <param name="strEncryptionKey">Key used to encrypt the querystring</param>
        /// <returns>Decrypted querystring</returns>
        public static string DecryptQuerystring(string strEncryptedQuerystring, string strEncryptionKey)
        {
            return Encryption64.Decrypt(HttpUtility.UrlDecode(strEncryptedQuerystring).Replace(" ", "+"),
                                        strEncryptionKey);
        }

        #endregion
    }
}